package cn.acmenms.service.impl;

import cn.acmenms.exception.BusinessException;
import cn.acmenms.mapper.SignInMapper;
import cn.acmenms.po.enums.MarkEnum;
import cn.acmenms.po.enums.PageSize;
import cn.acmenms.po.enums.SourceFrom;
import cn.acmenms.po.enums.TimeFormatEnum;
import cn.acmenms.po.model.*;
import cn.acmenms.po.query.SignInQuery;
import cn.acmenms.po.vo.PaginationResult;
import cn.acmenms.po.vo.SimplePage;
import cn.acmenms.po.vo.TokenUser;
import cn.acmenms.service.SignInService;
import cn.acmenms.service.UserService;
import cn.acmenms.utils.Constants;
import cn.acmenms.utils.LocalDateTimeUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @ClassName: SignInServiceImpl
 * @Description: 签到业务
 * @author: 神奇的鸭鸭
 * @Date: 2018/2/9 23:02
 */
@Service("signInService")
public class SignInServiceImpl implements SignInService{

    @Resource
    private SignInMapper<SignIn, SignInQuery> signInMapper;

    @Resource
    private UserService userService;

    @Override
    public SignInInfo findSignInInfoByUserId(Integer userId) {
        // 查询当日所有签到信息
        SignInInfo signInInfo = new SignInInfo();
        // 本周签到数量统计
        SignInQuery query = new SignInQuery();
        LocalDateTime now = LocalDateTime.now();
        query.setStartDate(LocalDateTimeUtils.minu(now, 6, ChronoUnit.DAYS));
        query.setEndDate(now);
        List<WeekSignIn> weekSignIns = this.signInMapper.selectWeekSignInCount(query);
        LocalDate curDate = LocalDate.now();
        boolean flag = false; // 还没有
        for (WeekSignIn weekSignIn: weekSignIns) {
            if(curDate.equals(weekSignIn.getSignDate().toLocalDate())) {
                flag = true; // 有了
                break;
            }
        }
        if(!flag){
            WeekSignIn weekSignIn = new WeekSignIn();
            weekSignIn.setCount(0);
            weekSignIn.setSignDate(now);
            weekSignIns.add(weekSignIn);
        }

        signInInfo.setWeekSignTotal(weekSignIns);

        if(null == userId) {
            signInInfo.setHaveSignInToday(Boolean.FALSE);
            signInInfo.setUserSignInCount(0);
        } else {
            // 查询用户所签到的总数量
            query = new SignInQuery();
            query.setUserId(userId);
            Integer userSignInCount = this.signInMapper.selectCount(query);
            signInInfo.setUserSignInCount(userSignInCount);
            // 查询用户当日是否签到
            query.setCurDate(now);
            Integer todayHaveSignIn = this.signInMapper.selectCount(query);
            if(todayHaveSignIn == 0) {
                signInInfo.setHaveSignInToday(Boolean.FALSE);
            } else {
                signInInfo.setHaveSignInToday(Boolean.TRUE);
            }
        }
        signInInfo.setWeek(LocalDateTimeUtils.getWeekCN(now));
        signInInfo.setCurDay(LocalDateTimeUtils.parseTime(now, TimeFormatEnum.MM_POINT_DD));
        return signInInfo;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = BusinessException.class)
    public SignIn doSignIn(TokenUser tokenUser, String sourceFrom) throws BusinessException {
        // 判断今天是否已经签到
        LocalDateTime now = LocalDateTime.now();
        SignInQuery query = new SignInQuery();
        query.setUserId(tokenUser.getUserId());
        query.setCurDate(now);
        Integer todaySignInCount = this.signInMapper.selectCount(query);
        if(todaySignInCount > 0) {
            throw new BusinessException("今天已经签到");
        }
        // 签到
        SignIn signIn = new SignIn();
        signIn.setUserId(tokenUser.getUserId());
        signIn.setUserName(tokenUser.getUserName());
        signIn.setUserIcon(tokenUser.getUserIcon());
        signIn.setSignDate(now);
        signIn.setSignTime(now);
        SourceFrom sourceFromEnum = SourceFrom.getSourceFormByValue(sourceFrom);
        if(null == sourceFromEnum){
            sourceFromEnum = SourceFrom.PC;
        }
        signIn.setSourceFrom(sourceFromEnum.getType());
        this.signInMapper.insert(signIn);
        // 判断是否连续签到7天
        LocalDateTime startDate = LocalDateTimeUtils.minu(now, 6, ChronoUnit.DAYS);
        query.setCurDate(null);
        query.setStartDate(startDate);
        query.setEndDate(now);
        // 获取连续签到次数
        Integer count = this.signInMapper.selectCount(query);
        // 写入积分 连续签到7天送20积分 普通签到送5积分
        int mark = MarkEnum.MARK_SIGIN.getMark();
        if(count >= Constants.CONTINUES_SIGIN_COUNT_SEVEN) {
            mark = MarkEnum.MARK_SIGIN_CONTINUE_SEVEN.getMark();
            signIn.setContinueSigIn(Boolean.TRUE);
        } else {
            signIn.setContinueSigIn(Boolean.FALSE);
        }
        userService.changeMark(tokenUser.getUserId(), mark);
        return signIn;
    }

    @Override
    public List<Calendar4SignIn> findUserSignInByYear(Integer userId, Integer year) throws BusinessException {
        LocalDateTime now = LocalDateTime.now();
        if(null == year) {
            year = now.getYear();
        }
        // 一年的年份
        final int yearMonth = 12;
        // 当月月份
        int curMonth = now.getMonthValue();
        // 查出用户签到记录
        SignInQuery query = new SignInQuery();
        query.setUserId(userId);
        query.setYear(year);
        List<SignIn> userSignInList = this.signInMapper.selectList(query);
        // 签到情况放到set中
        Set<String> signInSet = new HashSet<>();
        for (SignIn signIn: userSignInList) {
            String dateStr = LocalDateTimeUtils.parseTime(signIn.getSignDate(), TimeFormatEnum.YYYY_MM_DD);
            signInSet.add(dateStr);
        }
        // 获取日历信息
        List<Calendar4SignIn> resultList = new ArrayList<>();
        for (int i = 1; i <= yearMonth; i++) {
            Calendar4SignIn monthInfo = new Calendar4SignIn();
            // 0 代表前面补充0 2 代表长度为2 d 代表参数为正数型
            monthInfo.setMonth(String.format("%02d", i)); // 几月
            monthInfo.setMonthDays(LocalDateTimeUtils.getMonthTotalDay(year, i)); // 这月的总天数
            monthInfo.setBeforeMonthDays(LocalDateTimeUtils.getBeforeMonthTotalDay(year, i)); // 上个月的总天数
            monthInfo.setFristDay(LocalDateTimeUtils.getMonthFristDay(year, i)); // 月的第一天是(周1-周7)
            List<DaySignInfo> dayList = new ArrayList<>();
            // 遍历一个月的签到记录
            for (int j = 1; j <= monthInfo.getMonthDays(); j++) {
                DaySignInfo dayInfo = new DaySignInfo();
                String day = String.format("%02d", j);
                String curDay = year + "-" + monthInfo.getMonth() + "-" + day;
                dayInfo.setDay(day);
                // 判断是否是今天
                if(curDay.equals(LocalDateTimeUtils.parseTime(LocalDateTime.now(), TimeFormatEnum.YYYY_MM_DD))) {
                    dayInfo.setCurDay(Boolean.TRUE);
                } else {
                    dayInfo.setCurDay(Boolean.FALSE);
                }
                // 判断是否已经签到
                if(signInSet.contains(curDay)) {
                    dayInfo.setSignInType(Boolean.TRUE);
                } else {
                    dayInfo.setSignInType(Boolean.FALSE);
                }
                // 判断日期是当天之前还是之后
                if(i < curMonth) {
                    dayInfo.setBeforeNowDate(Boolean.TRUE);
                } else if(i == curMonth) {
                    // 如果是当月，就要判断具体日期
                    LocalDate date = LocalDate.parse("2018-12-13", TimeFormatEnum.YYYY_MM_DD.getFormatter());
                    if(date.isAfter(LocalDate.now())){
                        dayInfo.setBeforeNowDate(Boolean.TRUE);
                    } else {
                        dayInfo.setBeforeNowDate(Boolean.FALSE);
                    }
                } else {
                    dayInfo.setBeforeNowDate(Boolean.FALSE);
                }
                dayList.add(dayInfo);
            }
            monthInfo.setDayInfos(dayList);
            resultList.add(monthInfo);
        }
        return resultList;
    }

    @Override
    public PaginationResult<SignIn> findCurDaySigIn(SignInQuery query) throws BusinessException {
        query.setCurDate(LocalDateTime.now());
        Integer totalCount = this.signInMapper.selectCount(query); // 数据总数
        int pageSize = PageSize.SIZE20.getSize(); // 每页显示数量
        int pageNum = 0; // 第几页
        if(null != query.getPageNum()){
            pageNum = query.getPageNum();
        }
        SimplePage simplePage = new SimplePage(pageNum, totalCount, pageSize); // 动态分页条
        query.setPage(simplePage);
        List<SignIn> signInList = this.signInMapper.selectList(query);
        return new PaginationResult<>(simplePage, signInList);
    }
}